package com.carbon.core.util;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * xml
 *
 * @author czq
 * @date 2021-04-29
 */
public class XmlUtils {

    public static ElementBuilder elementBuilder(String elementName, Element targetElement, Document targetDocument) {
        return new ElementBuilder(elementName, targetElement, targetDocument);
    }

    public static class ElementBuilder {

        private final Element targetElement;

        private final Element newElement;

        public ElementBuilder(String elementName, Element targetElement, Document targetDocument) {
            this.targetElement = targetElement;
            this.newElement = targetDocument.createElement(elementName);
        }

        /**
         * 设置属性
         *
         * @param name  属性名
         * @param value 属性值
         * @return 构造者
         */
        public ElementBuilder setAttribute(String name, String value) {
            this.newElement.setAttribute(name, value);
            return this;
        }

        public ElementBuilder setAttributeMap(Map<String, ?> map) {
            Set<String> nameList = map.keySet();
            for (String name : nameList) {
                this.newElement.setAttribute(name, null != map.get(name) ? map.get(name).toString() : "");
            }
            return this;
        }

        public ElementBuilder setAttributeObject(Object object) {
            Map<String, Object> objectMap = MapUtils.objectToMap(object);
            return setAttributeMap(objectMap);
        }

        /**
         * 构建
         *
         * @return 构建完成的元素
         */
        public Element build() {
            targetElement.appendChild(newElement);
            return newElement;
        }
    }

    public static Document convertToDocument(File xmlFile) {
        FileInputStream stream;
        try {
            stream = new FileInputStream(xmlFile);
            return convertToDocument(stream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Document convertToDocument(String xmlStr) {
        return convertToDocument(new InputSource(new StringReader(xmlStr)));
    }

    public static Document convertToDocument(InputSource ins) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = factory.newDocumentBuilder();
            return builder.parse(ins);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Document convertToDocument(InputStream in) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = factory.newDocumentBuilder();
            return builder.parse(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取 xml 内 tagName 的标签
     *
     * @param document xml
     * @param tagName  标签名
     * @param index    第几个
     * @return element 匹配到的第 index 个
     */
    public static Element getElementByXml(Document document, String tagName, int index) {
        NodeList elements = document.getElementsByTagName(tagName);
        if (null != elements && elements.getLength() != 0) {
            if (index <= elements.getLength()) {
                return (Element) elements.item(index);
            }
        }
        return null;
    }

    /**
     * 获取 xml 内 tagName 的标签
     *
     * @param document xml
     * @param tagName  标签名
     * @return element 匹配到的第 1 个
     */
    public static Element getElementByXml(Document document, String tagName) {
        return getElementByXml(document, tagName, 0);
    }

    /**
     * 获取 element 内 tagName 的标签
     *
     * @param element element
     * @param tagName 标签名
     * @param index   第几个
     * @return element 匹配到的第 index 个
     */
    public static Element getElementByElement(Element element, String tagName, int index) {
        NodeList elements = element.getElementsByTagName(tagName);
        if (null != elements && elements.getLength() != 0) {
            if (index <= elements.getLength()) {
                return (Element) elements.item(index);
            }
        }
        return null;
    }

    /**
     * 获取 element 内 tagName 的标签
     *
     * @param element element
     * @param tagName 标签名
     * @return element 匹配到的第 1 个
     */
    public static Element getElementByElement(Element element, String tagName) {
        return getElementByElement(element, tagName, 0);
    }

    /**
     * 获取元素下面的所有元素
     *
     * @param element 元素
     * @param tagName 标签名
     * @return 元素集合
     */
    public static List<Element> getElementListByElement(Element element, String tagName) {
        NodeList elements = element.getElementsByTagName(tagName);
        return getElements(elements);
    }

    private static List<Element> getElements(NodeList elements) {
        List<Element> elementList = new ArrayList<>();
        if (null != elements && elements.getLength() != 0) {
            for (int i = 0, elementsSize = elements.getLength(); i < elementsSize; i++) {
                elementList.add((Element) elements.item(i));
            }
        }
        return elementList;
    }
}
